package com.ruoyi.client.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.client.domain.entity.BlogArticle;
import com.ruoyi.client.domain.entity.BlogComment;
import com.ruoyi.client.domain.entity.BlogUser;
import com.ruoyi.client.domain.vo.CommentVo;
import com.ruoyi.client.domain.vo.EchartsVo;
import com.ruoyi.client.mapper.BlogCommentMapper;
import com.ruoyi.client.service.IBlogArticleService;
import com.ruoyi.client.service.IBlogCommentService;
import com.ruoyi.client.service.IBlogUserService;
import com.ruoyi.common.core.utils.MapstructUtils;
import com.ruoyi.common.json.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 评论表 服务实现类
 * </p>
 *
 * @author fz
 * @since 2025-02-27
 */
@Service
public class BlogCommentServiceImpl extends ServiceImpl<BlogCommentMapper, BlogComment> implements IBlogCommentService {
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    IBlogUserService userService;
    @Autowired
    IBlogArticleService articleService;

    @Override
    public CommentVo saveComment(BlogComment comment) {
        save(comment);
        // 更新评论数
        UpdateWrapper<BlogArticle> wrapper = new UpdateWrapper<>();
        wrapper.setSql("comment_num = comment_num + 1")
            .eq("id", comment.getTargetId());
        articleService.update(wrapper);
        BlogComment comment1 = getById(comment);
        comment1.setLikedUserIds(new HashMap<Long,Boolean>());
        // 保存到mongodb中
        BlogComment save = mongoTemplate.save(comment1, "comment");
        CommentVo commentVo = MapstructUtils.convert(save, CommentVo.class);
        return commentVo;
    }

    @Override
    public List<CommentVo> getComment(Long id) {
        // 先看mongodb中有无数据，没有则查询mysql
        Query query = Query.query(Criteria.where("targetId").is(id));
        List<BlogComment> list = mongoTemplate.find(query, BlogComment.class);
        ArrayList<CommentVo> result = new ArrayList<>();
        Long userId = Long.valueOf((String) StpUtil.getLoginId());
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(v -> {
                BlogUser blogUser = JsonUtils.parseObject(v.getUserJson(), BlogUser.class);
                CommentVo vo = new CommentVo();
                MapstructUtils.convert(v,vo);

                // 设置当前用户是否点赞
                Map<Long, Boolean> likedUserIds = v.getLikedUserIds();
                Boolean aBoolean = likedUserIds.get(userId);
                if (aBoolean != null) {
                    vo.setCurrentUserIsLike(aBoolean ? "liked" : "disliked");
                }
                vo.setUser(blogUser);
                result.add(vo);
            });
            return result;
        }
        list = list(Wrappers.<BlogComment>lambdaQuery()
            .eq(BlogComment::getTargetId, id)
        );
        mongoTemplate.insert(list,BlogComment.class);
        list.forEach(v -> {
            BlogUser blogUser = JsonUtils.parseObject(v.getUserJson(), BlogUser.class);
            CommentVo vo = new CommentVo();
            MapstructUtils.convert(v,vo);
            vo.setUser(blogUser);
            result.add(vo);
        });
        return result;
    }

    @Override
    public CommentVo likeComment(BlogComment comment) {
        Query query = Query.query(Criteria.where("id").is(comment.getId()));
        BlogComment blogComment = mongoTemplate.findOne(query, BlogComment.class);
        Map<Long, Boolean> likedUserIds = blogComment.getLikedUserIds();
        if (CollectionUtil.isNotEmpty(likedUserIds) && likedUserIds.get(comment.getCurrentLikeUserId()) != null){
            Boolean result = likedUserIds.get(comment.getCurrentLikeUserId());
            if (result) {
                if (comment.getIsLike()){
                    // 取消点赞
                    blogComment.setLikeNum(blogComment.getLikeNum() - 1);
                    blogComment.getLikedUserIds().remove(comment.getCurrentLikeUserId());
                }
                else {
                    // 将喜欢设置为不喜欢
                    blogComment.setLikeNum(blogComment.getLikeNum() - 1);
                    blogComment.setDislikeNum(blogComment.getDislikeNum() + 1);
                    blogComment.getLikedUserIds().put(comment.getCurrentLikeUserId(),!result);
                }
            }
            else {
                if (!comment.getIsLike()) {
                    // 取消不喜欢
                    blogComment.setDislikeNum(blogComment.getDislikeNum() -1);
                    blogComment.getLikedUserIds().remove(comment.getCurrentLikeUserId());
                }
                else {
                    // 将不喜欢设置为喜欢
                    blogComment.setDislikeNum(blogComment.getDislikeNum() - 1);
                    blogComment.setLikeNum(blogComment.getLikeNum() + 1);
                    blogComment.getLikedUserIds().put(comment.getCurrentLikeUserId(),!result);
                }
            }
        }
        else {
            if (CollectionUtil.isEmpty(likedUserIds)) {
                likedUserIds = new HashMap<Long,Boolean>();
                blogComment.setLikedUserIds(likedUserIds);
            }
            // 未点赞
            likedUserIds.put(comment.getCurrentLikeUserId(),comment.getIsLike());
            if (comment.getIsLike()) {
                blogComment.setLikeNum(blogComment.getLikeNum() + 1);
            }
            else {
                blogComment.setDislikeNum(blogComment.getDislikeNum() + 1);
            }
        }
        BlogComment save = mongoTemplate.save(blogComment);
        Boolean aBoolean = save.getLikedUserIds().get(comment.getCurrentLikeUserId());
        CommentVo vo = MapstructUtils.convert(save, CommentVo.class);
        if (aBoolean != null) {
            vo.setCurrentUserIsLike(aBoolean ? "liked" : "disliked");
        }
        return vo;
    }
    @Override
    public List<EchartsVo> addLikeNum(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        // 查询点赞记录
        List<BlogComment> list = list(Wrappers.<BlogComment>lambdaQuery()
            .eq(BlogComment::getUserId, userId)
            .between(BlogComment::getCreateTime, startTime, endTime)
        );
        // 如果查询结果为空，直接返回空列表
        if (CollectionUtil.isEmpty(list)) {
            return generateEmptyResult(startTime.toLocalDate(), endTime.toLocalDate());
        }
        // 按日期分组统计点赞数
        Map<LocalDate, Long> detail = list.stream()
            .collect(Collectors.groupingBy(
                blogLike -> blogLike.getCreateTime().toLocalDate(),
                Collectors.counting()
            ));
        // 补全没有值的日期
        return generateResultWithMissingDates(detail, startTime.toLocalDate(), endTime.toLocalDate());
    }
    /**
     * 生成时间范围内的所有日期
     */
    private List<LocalDate> generateDateRange(LocalDate startDate, LocalDate endDate) {
        long numOfDays = ChronoUnit.DAYS.between(startDate, endDate) + 1; // 包括结束日期
        return Stream.iterate(startDate, date -> date.plusDays(1))
            .limit(numOfDays)
            .collect(Collectors.toList());
    }

    /**
     * 生成补全后的结果
     */
    private List<EchartsVo> generateResultWithMissingDates(Map<LocalDate, Long> detail, LocalDate startDate, LocalDate endDate) {
        List<EchartsVo> result = new ArrayList<>();
        List<LocalDate> dateRange = generateDateRange(startDate, endDate);

        for (LocalDate date : dateRange) {
            EchartsVo vo = new EchartsVo();
            vo.setName(date.getMonthValue() + "月" + date.getDayOfMonth() + "日");
            vo.setValue(detail.getOrDefault(date, 0L)); // 如果有值则使用，否则补全为0
            result.add(vo);
        }

        return result;
    }

    /**
     * 生成空结果（所有日期的点赞数为0）
     */
    private List<EchartsVo> generateEmptyResult(LocalDate startDate, LocalDate endDate) {
        List<EchartsVo> result = new ArrayList<>();
        List<LocalDate> dateRange = generateDateRange(startDate, endDate);

        for (LocalDate date : dateRange) {
            EchartsVo vo = new EchartsVo();
            vo.setName(date.getMonthValue() + "月" + date.getDayOfMonth() + "日");
            vo.setValue(0L); // 点赞数为0
            result.add(vo);
        }

        return result;
    }
}
